package kubayaxi.video.client.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import kubayaxi.video.client.request.login.LoginDTO;
import kubayaxi.video.client.request.login.LoginSendCodeDTO;
import kubayaxi.video.client.response.login.LoginVO;
import kubayaxi.video.client.service.ILoginService;
import kubayaxi.video.mybatis.auto.dao.ClientUserMapper;
import kubayaxi.video.mybatis.auto.model.ClientUser;
import kubayaxi.video.redis.constant.RedisConstant;
import kubayaxi.video.redis.util.RedisUtil;
import kubayaxi.video.service.base.common.enums.DeleteEnum;
import kubayaxi.video.service.base.common.request.BaseRequest;
import kubayaxi.video.service.base.util.ali.MessageUtil;
import kubayaxi.video.service.base.util.common.Asserts;
import kubayaxi.video.service.base.util.sm.SmartUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Random;
import java.util.regex.Pattern;

@Service
public class LoginServiceImpl implements ILoginService {

    @Resource
    private RedisUtil redisUtil;
    @Resource
    private MessageUtil messageUtil;
    @Resource
    private ClientUserMapper clientUserMapper;
    /**
     * 发送验证码
     */
    @Override
    public void sendCode(BaseRequest<LoginSendCodeDTO> dto) {
        LoginSendCodeDTO data = dto.getData();
        Asserts.isTrue(verifyPhone(data.getPhone()),"手机格式有误！");
        // 一分钟内不重复生成
        String key1 = RedisConstant.MES_REGIST_INTERVAL + data.getPhone();
        Asserts.isTrue(!redisUtil.hasKey(key1),"一分钟内不重复发送");
        // 生成验证码
        Random random = new Random();
        String code = String.valueOf(random.nextInt(9000) + 1000);
        try {
            messageUtil.send(data.getPhone(),code);
        } catch (Exception e) {
            Asserts.isTrue(false,"发送短信失败");
        }
        // 验证码存到redis
        String key2 = RedisConstant.MES_REGIST_PREFIX + data.getPhone();
        redisUtil.set(key2,code,RedisConstant.REDIS_DEFAULT_CODE_TIMEOUT);
        redisUtil.set(key1,code,RedisConstant.REDIS_MESSAGE_INTERVAL);
    }

    /**
     * 用户登录
     */
    @Override
    public LoginVO login(BaseRequest<LoginDTO> dto, HttpServletRequest request) {
        LoginDTO data = dto.getData(); //前端传递数据，包含手机号和验证码
        Asserts.isTrue(verifyPhone(data.getPhone()),"手机号格式错误");
        String key2 = RedisConstant.MES_REGIST_PREFIX+data.getPhone(); //验证码redis的key
        Asserts.isTrue(redisUtil.hasKey(key2),"验证码未生产或已过期");
        String code = redisUtil.get(key2).toString(); //redis通过key获取值转成字符串
        //设置6666验证码也可以通过
        Asserts.isTrue(data.getCode().equals(code) || data.getCode().equals("6666"),"验证码错误");
        redisUtil.del(key2); //使用过一次后删除redis缓存
        //查询对应手机号用户
        ClientUser one = clientUserMapper.selectOne(new LambdaQueryWrapper<ClientUser>()
                .eq(ClientUser::getPhone, data.getPhone())
                .eq(ClientUser::getDeleteStatus, DeleteEnum.NOT_DELETED.getCode()));
        String ip = ServletUtil.getClientIP(request); //获取用户当前ip
        if (ip.equals("0:0:0:0:0:0:0:1")) ip = "127.0.0.1"; //本机ip转换
        if (ObjectUtil.isNull(one)) { //用户未注册,先进行注册
            ClientUser clientUser = new ClientUser(); //new一个用户对象
            clientUser.setPhone(data.getPhone()); //设置手机号
            clientUser.setLoginIp(ip); //设置登录ip
            clientUser.setLastTime(LocalDateTime.now()); //设置最近登录时间
            int count = clientUserMapper.selectCount(null); //找到一共有多少用户
            clientUser.setNickName("客官-"+(count + 1)); //设置默认昵称
            int insert = clientUserMapper.insert(clientUser); //插入用户到数据库
            Asserts.isTrue(insert == 1, "添加用户失败");
            one = clientUser;
        } else { //用户已注册
            one.setLoginIp(ip); //设置登录ip
            one.setLastTime(LocalDateTime.now()); //设置最近登录时间
            int update = clientUserMapper.updateById(one); //更新用户信息
            Asserts.isTrue(update == 1, "更新用户信息失败");
        }
        String token = generateToken(one.getId()); //根据加密算法生成token
        LoginVO loginVO = new LoginVO(); // new返回登录信息
        loginVO.setToken(token); //设置token
        return loginVO;
    }

    public static boolean verifyPhone(String phone) {
        String regex = "^[1]([3-9])[0-9]{9}$";
        boolean isMatch = false;
        if (StrUtil.isEmpty(phone)) {
            return false;
        } else if (phone.length() != 11) {
            return false;
        } else {
            isMatch = Pattern.matches(regex, phone);
        }
        return isMatch;
    }

    private String generateToken(Long userId){
        JSONObject jsonObject = JSONUtil.createObj();
        jsonObject.set("userId", userId);
        jsonObject.set("time", System.currentTimeMillis());
        String sm4Str = SmartUtil.sm4Encrypt(SmartUtil.sm4, jsonObject.toString());
        redisUtil.set(RedisConstant.LOGIN_PREFIX + userId,sm4Str,RedisConstant.REDIS_DEFAULT_USER_TIMEOUT);
        return sm4Str;
    }
}
